package thread;

/**
 * @User: vitobo
 * @Date: 2024-08-02
 * @Description: 模拟实现阻塞队列
 *
 *  阻塞队列: 具有阻塞功能,队列在多线程环境下使用, 保证线程安全;
 *      保证线程安全,主要就是 加上锁, 使用synchronized
 *
 */


// 实现阻塞队列: 在普通队列上 加阻塞功能

class MyBlockingQueue{
    private int[] elem = new int[100];
    private int head = 0;
    private int tail = 0;
    private int size = 0;


    // 入队列
    public void put(int value) throws InterruptedException {
        synchronized (this){
            // 每次唤醒之后, 都会判断一下队列是否为满!
            while (size == elem.length){
                // 队列满了, 此时要产生阻塞
                this.wait();
            }
            elem[tail] = value;
            tail++;

            // 处理tail
            // tail = tail % elem.length;
            if(tail >= elem.length){
                tail = 0;
            }

            size++;
            // 唤醒take中的wait
            this.notify();
        }
    }

    // 出队列
    public Integer take() throws InterruptedException {
        int result = 0;
        synchronized (this){
            while (size == 0){
                // 队列空,不能出队列, 阻塞
                this.wait();
            }
            result = elem[head];
            head++;
            if(head >= elem.length){
                head = 0;
            }
            size--;
            // 唤醒put中的wait()
            this.notify();
        }
        return result;
    }
}

public class ThreadDemo23 {
    // 生产者消费者模型
    public static void main(String[] args) {
        MyBlockingQueue queue = new MyBlockingQueue();

        // 消费者
        Thread customer = new Thread(()->{
            // 循环取出阻塞队列中的元素
            while (true){
                try {
                    Integer result = queue.take();
                    System.out.println("消费元素:" + result);

                    // 生产速度大于 消费速度
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        customer.start();

        // 生产者
        Thread producer = new Thread(()->{
            int count = 0;
            while (true){
                try {
                    queue.put(count);
                    System.out.println("生产元素: " + count);
                    count++;

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        });

        producer.start();

    }



    public static void main1(String[] args) throws InterruptedException {
        MyBlockingQueue queue = new MyBlockingQueue();
        queue.put(11);
        queue.put(2);
        queue.put(3);
        queue.put(4);

        int result = 0;
        result = queue.take();
        System.out.println(result);

        result = queue.take();
        System.out.println(result);

        result = queue.take();
        System.out.println(result);

        result = queue.take();
        System.out.println(result);

        // 队列为空, 阻塞
        result = queue.take();
        System.out.println(result);
    }
}
